package cn.com.qtgl.apis.notification.comp.service;

import cn.com.qtgl.apis.notification.comp.proxy.NotificationProxy;
import cn.com.qtgl.apis.notification.model.view.NotificationChannelView;
import cn.hutool.core.collection.CollectionUtil;
import cn.melonlib.cores.commons.comp.dao.DaoUtils;
import cn.melonlib.cores.commons.comp.service.impl.WorkerBasicService;
import cn.melonlib.cores.commons.comp.utils.FilterTools;
import cn.melonlib.cores.identification.comp.messenger.MessengerUtils;
import cn.melonlib.cores.jpa.model.bean.impl.DefaultQuery;
import cn.melonlib.cores.model.anno.*;
import org.intellij.lang.annotations.Language;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.transaction.Transactional;

import cn.com.qtgl.apis.notification.model.entity.NotificationChannel;
import cn.com.qtgl.apis.notification.model.view.ChannelEdges;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

import static cn.melonlib.cores.commons.comp.service.impl.WorkerBasicService.ROOT_METHOD.*;
@Service
@WorkerService(
        module = "notification",
        model = @WorkerModel(
                modelType = NotificationChannel.class
        )
        ,ignores = {SAVE,REMOVE_BY_ID,REMOVE_BY_ID_LIST}
)
@WorkerComment("消息渠道管理")
public class NotificationChannelService extends WorkerBasicService<NotificationChannel> {

    @Resource
    @Lazy
    private NotificationProxy notification;

    @Resource
    private FilterTools filterTools;

    @Resource
    private DaoUtils daoUtils;

    @Resource
    private MessengerUtils messengerUtils;

    @WorkerStore
    @WorkerComment("更新消息渠道")
    @Transactional(value = Transactional.TxType.REQUIRED,rollbackOn = Exception.class)
    public List<NotificationChannel> syncRemoteChannels() throws Exception{
        List<NotificationChannel> channels=this.allChannels();
        if(CollectionUtil.isNotEmpty(channels)){
            return channels;
        }
        List<NotificationChannelView> channelViews=notification.channels()
                .getEdges().stream().map(ChannelEdges::getNode).collect(Collectors.toList());
        List<String> codes=channelViews.stream().map(NotificationChannelView::getCode).collect(Collectors.toList());
        @Language("HQL") String query="from NotificationChannel where "+
                daoUtils.filterToQl(filterTools.createFilters().addIn("code",codes).getConditionsMap());
        List<String> channelCodes=dao.<List<NotificationChannel>, DefaultQuery>search(new DefaultQuery(query,codes)).getResult()
                .stream().map(NotificationChannel::getCode).collect(Collectors.toList());
        return channelViews.stream().filter(v->!channelCodes.contains(v.getCode())).reduce(new ArrayList<NotificationChannel>(),(row, v)->{
            NotificationChannel notificationChannel=new NotificationChannel();
            BeanUtils.copyProperties(v,notificationChannel);
            try {
                messengerUtils.setMessengers(notificationChannel);
            }catch (Exception e){
                logger.error(e.getMessage(),e);
            }
            row.add(dao.save(notificationChannel).getResult());
            return row;
        },(r,v)->null);
    }

    @WorkerStore
    @WorkerComment("本系统启用消息渠道")
    @Transactional(value = Transactional.TxType.REQUIRED,rollbackOn = Exception.class)
    public List<NotificationChannel> activeChannels(
            @WorkerParameter(value = "channelCodes",comment = "需要激活使用的渠道",required = true) List<String> channelCodes) throws Exception{
        this.syncRemoteChannels();
        @Language("HQL") String updateQuery="update NotificationChannel set active = false";
        dao.updateQl(updateQuery, Collections.emptyList());
        dao.flush();
        @Language("HQL") String query="from NotificationChannel where "+
                daoUtils.filterToQl(filterTools.createFilters().addIn("code",channelCodes).getConditionsMap());
        return dao.<List<NotificationChannel>,DefaultQuery>search(new DefaultQuery(query,channelCodes)).getResult().stream().reduce(new ArrayList<NotificationChannel>(),(list,item)->{
            item.setActive(true);
            list.add(dao.save(item).getResult());
            dao.flush();
            return list;
        },(l,i)->null);
    }

    @WorkerQuery
    @WorkerComment("所有渠道信息")
    public List<NotificationChannel> allChannels(){
        @Language("HQL") String query="from NotificationChannel ";
        return dao.<List<NotificationChannel>,String>search(query).getResult();
    }

    @WorkerQuery
    @WorkerComment("可用渠道信息")
    public List<NotificationChannel> activeChannels(){
        @Language("HQL") String query="from NotificationChannel where active=?1";
        return dao.<List<NotificationChannel>,DefaultQuery>search(new DefaultQuery(query,List.of(true))).getResult();
    }
}
